package com.stake.web.controller;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.google.api.client.googleapis.auth.oauth2.draft10.GoogleAuthorizationRequestUrl;
import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.api.images.ImagesService;
import com.google.appengine.api.images.ImagesServiceFactory;
import com.google.code.linkedinapi.client.oauth.LinkedInApiConsumer;
import com.google.code.linkedinapi.client.oauth.LinkedInOAuthService;
import com.google.code.linkedinapi.client.oauth.LinkedInRequestToken;
import com.google.gson.Gson;
import com.stake.entity.UserInfo;

@Controller
@RequestMapping("/public")
public class HomeController {
	
	public static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(HomeController.class);
	
	private static final String SCOPE = "https://www.googleapis.com/auth/userinfo.email";
	private static final String CALLBACK_URL = "http://www.galaxy-space.com/public/googleRedirect.htm";
	
	private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
	private ImagesService imagesService = ImagesServiceFactory.getImagesService();

	// FILL THESE IN WITH YOUR VALUES FROM THE API CONSOLE
	private static final String CLIENT_ID = "916376634676.apps.googleusercontent.com";
	
	//final LinkedInApiClient client = factory.createLinkedInApiClient(accessTokenValue, tokenSecretValue);
	
	@Autowired
	@Qualifier("persistenceManagerFactory") 
	PersistenceManagerFactory persistenceManagerFactory;
	
	@Autowired
	@Qualifier("authenticationManager") 
	AuthenticationManager authenticationManager;
	
	@Autowired
	UserProfileController userProfileController;
	
	@InitBinder
	public void dateBinder(WebDataBinder binder) {
	            //The date format to parse or output your dates
	    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
	            //Create a new CustomDateEditor
	    CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
	            //Register it as custom editor for the Date type
	    binder.registerCustomEditor(Date.class, editor);
	}

	//@RequestMapping("stakeIndex.htm")
	public ModelAndView displayHoome(HttpServletRequest request){
		Map<String, Object> model = new HashMap<String, Object>();
		HttpSession session = request.getSession();
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if (authentication.getPrincipal() instanceof UserInfo) {
			UserInfo user = (UserInfo) authentication.getPrincipal();
			if(user.getFirstName() != null){
				session.setAttribute("sessionUserName", user.getFirstName() + " " + user.getLastName());
			} else {
				session.setAttribute("sessionUserName", user.getEmail());
			}
			
		}
		return new ModelAndView("stake.welcome", model);
	}
	
	@SuppressWarnings("unchecked")
	//@RequestMapping("index.htm")
	public ModelAndView displayVisHome(HttpServletRequest request){
		Map<String, Object> model = new HashMap<String, Object>();
		HttpSession session = request.getSession();
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if (authentication.getPrincipal() instanceof UserInfo) {
			UserInfo user = (UserInfo) authentication.getPrincipal();
			PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
			Query query = manager.newQuery(UserInfo.class);
			query.setFilter("email == userNameParam");
			query.declareParameters("String userNameParam");
			UserInfo userEntity = ((List<UserInfo>) query.execute(user.getEmail())).get(0);
			manager.close();
			session.setAttribute("sessionUserName", user.getFirstName() + " " + user.getLastName());
			if(!userEntity.getQanswered()){
				//Questionnaire not answered | taking user to questions page
				model.put("param1", "showQuestionnaire");
			}
		}
		return new ModelAndView("stake.welcome", model);
	}
	
	@RequestMapping("/nexus2.htm") 
	public ModelAndView showNexus2View(){
		return new ModelAndView("nexus2.welcome"); 
	}
	
	@RequestMapping("/nexus2Banner.htm") 
	public ModelAndView showBannerView(){
		return new ModelAndView("nexus2BannerPage"); 
	}
	
	@RequestMapping("/n2registration.htm") 
	public ModelAndView showN2RegistrationForm(){
		UserInfo user = new UserInfo();
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("uploadurl", com.google.appengine.api.blobstore.BlobstoreServiceFactory.getBlobstoreService().createUploadUrl("/public/n2uploadImg.htm") );
		model.put("newUser", user);
		return new ModelAndView("nexus2Registration", model); 
	}
	
	@RequestMapping("/n2Login.htm") 
	public ModelAndView showN2LoginForm(){
		Map<String, Object> model = new HashMap<String, Object>();
		return new ModelAndView("n2Login", model);
	}
	
	@RequestMapping("/n2uploadImg.htm") 
	public @ResponseBody String n2UploadImage(HttpServletRequest request){
		Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(request); 
        List<BlobKey> blobKey = blobs.get("uploadedFile");
        
		if(blobKey.size() == 1){
			return blobKey.get(0).getKeyString(); 
			//userEntity.setImageBlobKey(blobKey.get(0).getKeyString());
		} else {
			logger.error("Image upload failed.... ");
		}		
		return "Error occourred";
	}
	
	@RequestMapping("/n2servingImgUrl.htm") 
	public @ResponseBody String getServingUrl(@RequestParam("blobkey") String blobKey){ 
		Map<String, String> model = new HashMap<String, String>();
		model.put("servingurl", imagesService.getServingUrl(new BlobKey(blobKey)));
		model.put("uploadurl", com.google.appengine.api.blobstore.BlobstoreServiceFactory.getBlobstoreService().createUploadUrl("/public/n2uploadImg.htm") );
		return new Gson().toJson(model); 
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/n2registerUser.htm") 
	public @ResponseBody String registerN2User(@ModelAttribute("newUser") UserInfo user, HttpServletRequest request){
		Map<String, String> model = new HashMap<String, String>();
		List<String> authorities = new ArrayList<String>();
		authorities.add("ROLE_USER");
        user.setAuthorities(authorities);
        user.setEnabled(Boolean.TRUE);
        PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
        Query query = manager.newQuery(UserInfo.class);
		query.setFilter("email == userNameParam");
		query.declareParameters("String userNameParam");
		List<UserInfo> userEntities = (List<UserInfo>) query.execute(user.getEmail()); 
		if(userEntities.size() > 0){
			model.put("result", "failure");
			model.put("message", "Email Address already exists.");
			return new Gson().toJson(model); 
		}
        user = manager.makePersistent(user);
        user = manager.detachCopy(user);
        manager.close();
		UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword());
		Authentication authentication = authenticationManager.authenticate(authToken);
		SecurityContextHolder.getContext().setAuthentication(authentication);
		model.put("result", "success");
		return new Gson().toJson(model); 
	}
	
	
	@SuppressWarnings("unchecked")
	@RequestMapping("nexusIndex.htm")
	public ModelAndView displayNexusHome(HttpServletRequest request){
		Map<String, Object> model = new HashMap<String, Object>();
		HttpSession session = request.getSession();
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if (authentication.getPrincipal() instanceof UserInfo) {
			UserInfo user = (UserInfo) authentication.getPrincipal();
			PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
			Query query = manager.newQuery(UserInfo.class);
			query.setFilter("email == userNameParam");
			query.declareParameters("String userNameParam");
			UserInfo userEntity = ((List<UserInfo>) query.execute(user.getEmail())).get(0);
			manager.close();
			if(userEntity.getFirstName() != null && user.getFirstName() == null){
				user.setFirstName(userEntity.getFirstName());
				user.setLastName(userEntity.getLastName());				
				session.setAttribute("sessionUserName", userEntity.getFirstName() + " " + userEntity.getLastName());
			} else if(userEntity.getCompanyName() != null){
				user.setCompanyName(userEntity.getCompanyName());
				session.setAttribute("sessionUserName", userEntity.getCompanyName());
			} else if(userEntity.getCompanyName() == null && userEntity.getFirstName() == null){
				session.setAttribute("sessionUserName", userEntity.getEmail());
			} else {
				session.setAttribute("sessionUserName", userEntity.getFirstName() + " " + userEntity.getLastName());
			}
			
			if(!userEntity.getQanswered()){
				//return userProfileController.showQuestionnaireForm("true");
			}
		}
		return new ModelAndView("nexus.welcome", model);
	}
	
	@RequestMapping("forgotPassword.htm") 
	public ModelAndView displayForgotPassword(){
		
		return new ModelAndView("forgotPasswordView"); 
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping("forgotPasswordSubmit.htm") 
	public @ResponseBody String displayForgotPasswordSubmit(@RequestParam("email") String email){
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		Query query = manager.newQuery(UserInfo.class);
		query.setFilter("email == userNameParam");
		query.declareParameters("String userNameParam");
		List<UserInfo> resultList =(List<UserInfo>) query.execute(email);
		UserInfo userEntity = null;
		Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);
        StringBuilder builder = new StringBuilder();
		if(resultList.size() > 0){
			userEntity = ((List<UserInfo>) query.execute(email)).get(0);
			try {
	            Message msg = new MimeMessage(session);
	            msg.setFrom(new InternetAddress("admin@galaxy-space.com", "Speaker Nexus"));
	            msg.addRecipient(Message.RecipientType.TO,
	                             new InternetAddress(email, userEntity.getFirstName() + " " + userEntity.getLastName()));
	            msg.setSubject("Your Password for Speaker Nexus.");
	            builder.append("Your Password: " + userEntity.getPassword());
	            builder.append("\n...");
	            builder.append("\nSpeaker Nexus Team");
	            msg.setText(builder.toString());
	            Transport.send(msg);
	        } catch (Exception e) {
	            System.out.println(e.getMessage());
	            logger.error("", e);
	        } 
		} else {
			// not implemented.. 
		}
		return "Email Will be sent to you for furthur instructions."; 
	}
	
	//@RequestMapping("vis/aboutUs.htm") 
	public ModelAndView displayVisAboutUs(){
		return new ModelAndView("visAboutUs"); 
	}
	
	//@RequestMapping("vis/services.htm") 
	public ModelAndView displayVisServices(){
		return new ModelAndView("visServices"); 
	}
	
	//@RequestMapping("vis/contactUs.htm") 
	public ModelAndView displayVisContactUs(){
		return new ModelAndView("visContactUs"); 
	}
	
	//@RequestMapping("vis/visHome.htm") 
	public ModelAndView displayVisHome(){
		return new ModelAndView("visHome"); 
	}
	
	//@RequestMapping("vis/whyUs.htm") 
	public ModelAndView displayWhyUs(){
		return new ModelAndView("visWhyUs");
	}
	
	@RequestMapping("welcomePane.htm")
	public ModelAndView welcomePane(){
		return new ModelAndView("welcomePane");
	}
	
	@RequestMapping("login.htm") 
	public ModelAndView login(@RequestParam("source") String loginSource, HttpSession session){
		if(loginSource.equalsIgnoreCase("google")){
			GoogleAuthorizationRequestUrl url = new GoogleAuthorizationRequestUrl();
			url.clientId = CLIENT_ID;
			url.scope = SCOPE;
			url.redirectUri = CALLBACK_URL;
			url.state = "/profile";
			url.responseType = "code";
			return new ModelAndView("redirect:" + url.build());
		} else if(loginSource.equalsIgnoreCase("linkedin")){
			
			final String consumerKeyValue = "57vupwf7qm04";
    		final String consumerSecretValue = "aHh3om7Zf9q5esFS";
    		final String callbackUrl = "http://www.galaxy-space.com/public/linkedin/authRedirect.htm";
    		
    		
    		
    		
    		
    		final LinkedInOAuthService oauthService2 = new LinkedInOAuthServiceImpl(new LinkedInApiConsumer(consumerKeyValue, consumerSecretValue));
    		
    		System.out.println("Fetching request token from LinkedIn...");
    		
    		LinkedInRequestToken requestToken = oauthService2.getOAuthRequestToken(callbackUrl);
    		session.setAttribute("request_token", requestToken.getToken());
    		session.setAttribute("token_secret", requestToken.getTokenSecret());
    		session.setAttribute("requestToken", requestToken);
    		
            String authUrl = requestToken.getAuthorizationUrl(); 
            authUrl = authUrl.replace("authorize", "authenticate");
            
            System.out.println("Request token: " + requestToken.getToken());
            System.out.println("Token secret: " + requestToken.getTokenSecret());
            System.out.println("Expiration time: " + requestToken.getExpirationTime());
            System.out.println("authurl : " + authUrl);
            return new ModelAndView("redirect:" + authUrl);
		}
		return new ModelAndView("login");
	}
	
	//@RequestMapping("/vis/login.htm") 
	public ModelAndView visLogin(@RequestParam("source") String loginSource){
		if(loginSource.equalsIgnoreCase("google")){
			GoogleAuthorizationRequestUrl url = new GoogleAuthorizationRequestUrl();
			url.clientId = CLIENT_ID;
			url.scope = SCOPE;
			url.redirectUri = CALLBACK_URL;
			url.state = "/profile";
			url.responseType = "code";
			return new ModelAndView("redirect:" + url.build());
		}
		return new ModelAndView("visLogin");
	}
	
	//@RequestMapping("vis/sendEmail.htm") 
	public @ResponseBody String visSendEmail(){
		
		return "Message Sent Successfully";
	}
	
	@RequestMapping("showRegistrationForm.htm")
	public ModelAndView showRegistrationForm(){
		UserInfo user = new UserInfo();
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("newUser", user);
		return new ModelAndView("registrationForm", model);
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping("registerUser.htm") 
	public @ResponseBody String registerUser(@ModelAttribute("newUser") UserInfo user, HttpServletRequest request){
		logger.info("user " + user.getEmail());
		List<String> authorities = new ArrayList<String>();
		authorities.add("ROLE_USER");
        user.setAuthorities(authorities);
        user.setEnabled(Boolean.TRUE);
        user.setQanswered(Boolean.FALSE);
        PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
        Query query = manager.newQuery(UserInfo.class);
		query.setFilter("email == userNameParam");
		query.declareParameters("String userNameParam");
		List<UserInfo> userEntities = (List<UserInfo>) query.execute(user.getEmail()); 
		if(userEntities.size() > 0){
			// user already exists
			return "Email Address already exists.";
		}
        user = manager.makePersistent(user);
        user = manager.detachCopy(user);
        manager.close();
		UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword());
		Authentication authentication = authenticationManager.authenticate(authToken);
		SecurityContextHolder.getContext().setAuthentication(authentication);
		StringBuilder registerResponse = new StringBuilder("success"); 
		return registerResponse.toString();
	}
	
	@SuppressWarnings("unchecked")
	//@RequestMapping("/googleRedirect.htm") 
	public ModelAndView googleRedirectCloseWindow(HttpServletRequest request){
		Map<String, String> userInfoMap = (Map<String, String>) request.getAttribute("newGoogleUser"); 
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		
		Query query = manager.newQuery(UserInfo.class);
		query.setFilter("userName == userNameParam");
		query.declareParameters("String userNameParam");
		List<UserInfo> userEntities = (List<UserInfo>) query.execute(userInfoMap.get("email")); 
		UserInfo newUser = new UserInfo();
		if(userEntities.size() > 0){
			// user already exists
			newUser = userEntities.get(0);
		} else {
			List<String> authorities = new ArrayList<String>();
			authorities.add("ROLE_USER");
			newUser.setAuthorities(authorities);
			newUser.setEnabled(Boolean.TRUE);
			newUser.setUserName(userInfoMap.get("email") );
			newUser.setFirstName(userInfoMap.get("given_name"));
			newUser.setLastName(userInfoMap.get("family_name"));
			newUser.setPassword("google");
			newUser = manager.makePersistent(newUser);
			newUser = manager.detachCopy(newUser);
	        manager.close();
		}
		UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(newUser.getEmail(), newUser.getPassword());
		Authentication authentication = authenticationManager.authenticate(authToken);
		SecurityContextHolder.getContext().setAuthentication(authentication);
		return new ModelAndView("auth_success_close");
	}
	
	//@RequestMapping("/googleLogin.htm")
	public String launchOauth() throws IOException {
		GoogleAuthorizationRequestUrl url = new GoogleAuthorizationRequestUrl();
		url.clientId = CLIENT_ID;
		url.scope = SCOPE;
		url.redirectUri = CALLBACK_URL;
		url.state = "/profile";
		url.responseType = "code";
		return "redirect:" + url.build();
	}
	
	@RequestMapping("/sampleMapping.htm")
    public ModelAndView testStake() throws IOException{
			Map<String, Object> model = new HashMap<String, Object>();
			model.put("message1", "Hello Spring");
           return new ModelAndView("samleMappingPage", model);
    }
	
	
}


